/**
 * Copyright (c) 2019-2029, wwww.kiwipeach.cn (liuburu@qq.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * https://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package open.kiwipeach.autoconfigure.web.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

/**
 * http请求辅助类
 *
 * @author kiwipeach
 * @since 1.0
 */
@Slf4j
public class HttpBaseUtil {

    /**
     * get公共方法
     *
     * @param uri 请求地址
     * @return 返回相应结果
     * @throws IOException
     */
    protected static String getResponse(URI uri) throws IOException {
        log.warn("GET:三方登陆请求:{}", uri.toString());
        //CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        CloseableHttpClient httpclient = createSSLClientDefault();
        HttpGet httpGet = new HttpGet(uri);
        //gitee 需要设置代理，否则会出出现403错误
        httpGet.setHeader(new BasicHeader("user-agent", "*"));
        CloseableHttpResponse httpResponse = httpclient.execute(httpGet);
        String response = EntityUtils.toString(httpResponse.getEntity());
        log.warn("GET:三方登陆返回:{}", response);
        return response;
    }

    /**
     * post公共方法
     *
     * @param uri 请求地址
     * @return 返回相应结果
     * @throws IOException
     */
    protected static String postResponse(URI uri) throws IOException {
        log.warn("POST:三方登陆请求:{}", uri.toString());
        // 组装post请求参数
        URIBuilder uriBuilder = new URIBuilder(uri);
        // 设置头信息，并发送post请求
        String postUri = new StringBuffer(uriBuilder.getScheme()).append("://").append(uriBuilder.getHost()).append(uri.getPath()).toString();
        HttpPost httpPost = new HttpPost(postUri);
        httpPost.setHeader(new BasicHeader("Content-Type", "application/x-www-form-urlencoded"));
        //gitee需要设置代理，否则会出出现403错误
        httpPost.setHeader(new BasicHeader("user-agent", "*"));
        List<NameValuePair> nvps = new ArrayList<>();
        List<NameValuePair> queryParams = uriBuilder.getQueryParams();
        for (NameValuePair nameValuePair : queryParams) {
            nvps.add(new BasicNameValuePair(nameValuePair.getName(), nameValuePair.getValue()));
        }
        httpPost.setEntity(new UrlEncodedFormEntity(nvps));
        //CloseableHttpClient httpclient = HttpClientBuilder.create().build();
        CloseableHttpClient httpclient = createSSLClientDefault();
        CloseableHttpResponse httpResponse = httpclient.execute(httpPost);
        String response = EntityUtils.toString(httpResponse.getEntity());
        log.warn("POST:三方登陆返回:{}", response);
        return response;
    }

    /**
     * 自定义 CloseableHttpClient ，客户端向服务器发送https请求时，会验证服务端的证书状态，可以设置信任所有证书，绕过这一步
     * 目的是避免：PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException 异常
     *
     * @return 返回CloseableHttpClient对象
     */
    private static CloseableHttpClient createSSLClientDefault() {
        try {
            //使用 loadTrustMaterial() 方法实现一个信任策略，信任所有证书
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                // 信任所有
                @Override
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            }).build();
            //NoopHostnameVerifier类:  作为主机名验证工具，实质上关闭了主机名验证，它接受任何
            //有效的SSL会话并匹配到目标主机。
            HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
            return HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        return HttpClients.createDefault();

    }


}
